<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <title>Base Tests</title>

    <script src="../../../build/yui/yui.js"></script>

    <style type="text/css">
        #console .yui3-console-entry {
            padding:2px;
            margin:0px;
            min-height:0;
        }

        #console .yui3-console-entry-fail .yui3-console-entry-cat {
            background-color:red;
        }

        #console .yui3-console-entry-pass .yui3-console-entry-cat {
            background-color:green;
        }

        #console .yui3-console-entry-perf .yui3-console-entry-cat {
            background-color:blue;
        }

        #console {
            position:static;
        }

        html, body {
            height:100%;
        }
    </style>
</head>
<body class="yui3-skin-sam">
<div id="testbed" class="yui3-skin-foo"></div>
<script>
YUI({useBrowserConsole:false, filter:"raw"}).use('test', 'base', 'console', function (Y) {

    // NOTE: Attribute's unit tests cover a large section of Base's functionality when it comes to dealing with attributes.

    var suite = new Y.Test.Suite("Base Tests");

    suite.add(new Y.Test.Case({

        name : "BaseBuild",

        "test:create-basic": function () {

            var expectedMethodCalls = [
                "ext1::constructor", 
                "myClass::initializer",
                "ext1::constructor", 
                "myClass::initializer", 
                "myClass::methodOne",
                "myClass::methodOne",
                "ext1::extOne",
                "ext1::extOne"],

                actualMethodCalls = [];

            function Ext1() {
                actualMethodCalls.push("ext1::constructor");
            }

            Ext1.prototype.extOne = function() {
                actualMethodCalls.push("ext1::extOne");
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
                
                initializer: function() {
                    actualMethodCalls.push("myClass::initializer");
                },

                methodOne: function() {
                    actualMethodCalls.push("myClass::methodOne");
                }

            }, {
                STATIC_ONE: "static_one"
            });

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass({foo:true});
            var o2 = new MyClass({foo:true});

            Y.Assert.isFunction(o1.extOne, "Extension method extOne not found on o1");
            Y.Assert.isFunction(o2.extOne, "Extension method extOne not found on o2");

            Y.Assert.isFunction(o1.methodOne, "Prototype method methodOne not found on o1");
            Y.Assert.isFunction(o2.methodOne, "Prototype method methodOne not found on o2");

            Y.Assert.areEqual(o1.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o1's constructor");
            Y.Assert.areEqual(o2.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o2's constructor");
            
            Y.Assert.areEqual(o1.constructor.NAME, "myClass", "NAME not found on o1's constructor");
            Y.Assert.areEqual(o2.constructor.NAME, "myClass", "NAME not found on o2's constructor"); 

            o1.methodOne();
            o2.methodOne();

            o1.extOne();
            o2.extOne();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:mix-basic": function() {

            var expectedMethodCalls = [
                "myClass::constructor",
                "ext1::constructor",
                "myClass::initializer",
                "myClass::constructor",
                "ext1::constructor",
                "myClass::initializer", 
                "myClass::methodOne",
                "myClass::methodOne",
                "ext1::extOne",
                "ext1::extOne"],

                actualMethodCalls = [];

            function Ext1() {
                actualMethodCalls.push("ext1::constructor");
            }

            Ext1.prototype.extOne = function() {
                actualMethodCalls.push("ext1::extOne");
            };

            function MyClass(config) {
                actualMethodCalls.push("myClass::constructor");
                MyClass.superclass.constructor.apply(this, arguments);
            }

            Y.extend(MyClass, Y.Base, {
                
                initializer: function() {
                    actualMethodCalls.push("myClass::initializer");
                },

                methodOne: function() {
                    actualMethodCalls.push("myClass::methodOne");
                }

            }, {
                STATIC_ONE: "static_one",
                NAME: "myClass"
            });

            Y.Base.mix(MyClass, [Ext1]);             

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass();
            var o2 = new MyClass();

            Y.Assert.isFunction(o1.extOne, "Extension method extOne not found on o1");
            Y.Assert.isFunction(o2.extOne, "Extension method extOne not found on o2");

            Y.Assert.isFunction(o1.methodOne, "Prototype method methodOne not found on o1");
            Y.Assert.isFunction(o2.methodOne, "Prototype method methodOne not found on o2");

            Y.Assert.areEqual(o1.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o1's constructor");
            Y.Assert.areEqual(o2.constructor.STATIC_ONE, "static_one", "STATIC_ONE not found on o2's constructor"); 

            o1.methodOne();
            o2.methodOne();

            o1.extOne();
            o2.extOne();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:initializer": function() {
            var expectedMethodCalls = [
                "ext1::constructor", 
                "myClass::initializer",
                "ext1::initializer", 
                "ext1::constructor", 
                "myClass::initializer",
                "ext1::initializer"],

                actualMethodCalls = [];

            function Ext1(cfg) {
                actualMethodCalls.push("ext1::constructor");
                Y.Assert.isNotUndefined(cfg);
            }

            Ext1.prototype.initializer = function(cfg) {
                actualMethodCalls.push("ext1::initializer");
                Y.Assert.isNotUndefined(cfg);
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
                initializer: function(cfg) {
                    actualMethodCalls.push("myClass::initializer");
                    Y.Assert.isNotUndefined(cfg);
                }
            });

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass({foo:true});
            var o2 = new MyClass({foo:true});

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },
        
        "test:destructor": function() {
            var expectedMethodCalls = [
                "ext1::destructor",
                "myClass::destructor",
                "ext1::destructor",
                "myClass::destructor"],

                actualMethodCalls = [];

            function Ext1(cfg) {}

            Ext1.prototype.destructor = function(cfg) {
                actualMethodCalls.push("ext1::destructor");
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
                destructor: function(cfg) {
                    actualMethodCalls.push("myClass::destructor");
                }
            });

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass({foo:true});
            var o2 = new MyClass({foo:true});

            o1.destroy();
            o2.destroy();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:attrs" : function() {

            var actualMethodCalls = [],
                expectedMethodCalls = [
                    "ext1::attr2::setter", // once for lazy o1 - This was news to me: we should optimize it as part off Attr performance
                    "ext1::attr2::setter", // once for set o1
                    "ext1::attr2::setter", // once for lazy o2
                    "ext1::attr2::setter"  // once for set o2
                ];

            function Ext1() {}

            Ext1.ATTRS = {
                attr1 : {
                    value:"attr1-ext1"
                },
                attr2 : {
                    value:"attr2-ext1",
                    setter: function(val) {
                        actualMethodCalls.push("ext1::attr2::setter");
                        return val;
                    }
                },
                attr3: {
                    value:"attr3-ext1"
                }
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1]);

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass();
            var o2 = new MyClass();
            
            o1.set("attr2", "foo");
            o2.set("attr2", "foo");

            Y.Assert.areEqual("attr1-ext1", o1.get("attr1"), "o1 attr1 incorrect");
            Y.Assert.areEqual("attr1-ext1", o2.get("attr1"), "o2 attr1 incorrect");
            
            Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
            Y.Assert.areEqual("foo", o2.get("attr2"), "o2 attr2 incorrect");
            
            Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
            Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:aggregates" : function() {

            function Ext1() {}

            Ext1.HTML_PARSER = {
                a:"aa",
                b:"bb"
            };

            function MyWidget(config) {
                MyWidget.superclass.constructor.apply(this, arguments);
            }

            Y.extend(MyWidget, Y.Base, {}, {

                HTML_PARSER : {
                    a:"a"
                },

                _buildCfg : {
                    aggregates : ["HTML_PARSER"]
                }
            });

            var MyClass = Y.Base.create("myClass", MyWidget, [Ext1]);

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass();
            var o2 = new MyClass();

            Y.ObjectAssert.areEqual({a:"aa", b:"bb"}, o1.constructor.HTML_PARSER, "o1 HTML_PARSER not aggregated correctly");
            Y.ObjectAssert.areEqual({a:"aa", b:"bb"}, o2.constructor.HTML_PARSER, "o2 HTML_PARSER not aggregated correctly");

        },

        "test:overrides-ext-wins" : function() {

            var actualMethodCalls = [],
                expectedMethodCalls = [
                    "ext1::attr2::setter", // once for lazy o1
                    "ext1::attr2::setter", // once for set o1
                    "ext1::attr2::setter", // once for lazy o2
                    "ext1::methodOne",
                    "ext1::methodOne"
                ];

            function Ext1() {}

            Ext1.prototype.methodOne = function() {
                actualMethodCalls.push("ext1::methodOne");
            };

            Ext1.ATTRS = {
                attr1 : {
                    value:"attr1-ext1"
                },
                attr2 : {
                    value:"attr2-ext1",
                    setter: function(val) {
                        actualMethodCalls.push("ext1::attr2::setter");
                        return val;
                    }
                },
                attr3: {
                    value:"attr3-ext1"
                }
            };

            function MyClass() {
                MyClass.superclass.constructor.apply(this, arguments);
            }
            
            MyClass.NAME = "myClass";

            MyClass.ATTRS = {
                attr1 : {
                    value:"attr1-myClass"
                },
                attr2 : {
                    value:"attr2-myClass",
                    setter: function(val) {
                        actualMethodCalls.push("myClass::attr2::setter");
                        return val;
                    }
                },
                attr4 : {
                    value:"attr4-myClass"
                }
            };

            Y.extend(MyClass, Y.Base, {
                methodOne : function() {
                    actualMethodCalls.push("myClass::methodOne");
                }
            });
            Y.Base.mix(MyClass, [Ext1]);

            // using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass();
            var o2 = new MyClass();

            // only set o1
            o1.set("attr2", "foo");

            Y.Assert.areEqual("attr1-ext1", o1.get("attr1"), "o1 attr1 incorrect");
            Y.Assert.areEqual("attr1-ext1", o2.get("attr1"), "o2 attr1 incorrect");

            Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
            Y.Assert.areEqual("attr2-ext1", o2.get("attr2"), "o2 attr2 incorrect");
            
            Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
            Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");

            Y.Assert.areEqual("attr4-myClass", o1.get("attr4"), "o1 attr4 incorrect");
            Y.Assert.areEqual("attr4-myClass", o2.get("attr4"), "o2 attr4 incorrect");

            o1.methodOne();
            o2.methodOne();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:overrides-host-wins" : function() {

            var actualMethodCalls = [],
                expectedMethodCalls = [
                    "myClass::attr2::setter", // once for lazy o1
                    "myClass::attr2::setter", // once for set o1
                    "myClass::attr2::setter", // once for lazy o2
                    "myClass::methodOne",
                    "myClass::methodOne"
                ];

            function Ext1() {}
            
            Ext1.prototype.methodOne = function() {
                actualMethodCalls.push("ext1::methodOne");
            };

            Ext1.ATTRS = {
                attr1 : {
                    value:"attr1-ext1"
                },
                attr2 : {
                    value:"attr2-ext1",
                    setter: function(val) {
                        actualMethodCalls.push("ext1::attr2::setter");
                        return val;
                    }
                },
                attr3: {
                    value:"attr3-ext1"
                }
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1], {
                methodOne : function() {
                    actualMethodCalls.push("myClass::methodOne");
                }
            }, { 
                ATTRS : {
                    attr1 : {
                        value:"attr1-myClass"
                    },
                    attr2 : {
                        value:"attr2-myClass",
                        setter: function(val) {
                            actualMethodCalls.push("myClass::attr2::setter");
                            return val;
                        }
                    },
                    attr4 : {
                        value:"attr4-myClass"
                    }
                }
            });

            // Using 2 instances, just to make sure nothing static/prototype related gets broken by the 1st instance
            var o1 = new MyClass();
            var o2 = new MyClass();

            // only set o1
            o1.set("attr2", "foo");

            Y.Assert.areEqual("attr1-myClass", o1.get("attr1"), "o1 attr1 incorrect");
            Y.Assert.areEqual("attr1-myClass", o2.get("attr1"), "o2 attr1 incorrect");

            Y.Assert.areEqual("foo", o1.get("attr2"), "o1 attr2 incorrect");
            Y.Assert.areEqual("attr2-myClass", o2.get("attr2"), "o2 attr2 incorrect");

            Y.Assert.areEqual("attr3-ext1", o1.get("attr3"), "o1 attr3 incorrect");
            Y.Assert.areEqual("attr3-ext1", o2.get("attr3"), "o2 attr3 incorrect");

            Y.Assert.areEqual("attr4-myClass", o1.get("attr4"), "o1 attr4 incorrect");
            Y.Assert.areEqual("attr4-myClass", o2.get("attr4"), "o2 attr4 incorrect");

            o1.methodOne();
            o2.methodOne();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },

        "test:multiext-complex" : function() {

            var actualMethodCalls = [],
                expectedMethodCalls = [
                    "ext1::constructor",
                    "ext2::constructor", 
                    "myClass::initializer",
                    "ext1::initializer",
                    "ext2::initializer",
                    "ext1::constructor",
                    "ext2::constructor", 
                    "myClass::initializer",
                    "ext1::initializer",
                    "ext2::initializer",
                    "ext2::attr3::setter",
                    "ext2::attr3::setter",
                    "myClass::methodOne",
                    "myClass::methodOne",
                    "myClass::methodTwo",
                    "myClass::methodTwo",
                    "ext2::methodThree",
                    "ext2::methodThree",
                    "ext2::methodFour",
                    "ext2::methodFour",
                    "myClass::methodFive",
                    "myClass::methodFive"
                ];

            function Ext1() {
                actualMethodCalls.push("ext1::constructor");
            }

            Ext1.prototype.initializer = function() {
                actualMethodCalls.push("ext1::initializer");
            };

            Ext1.prototype.methodTwo = function() {
                actualMethodCalls.push("ext1::methodTwo");
            };

            Ext1.prototype.methodThree = function() {
                actualMethodCalls.push("ext1::methodThree");
            };

            Ext1.ATTRS = {
                attr2 : {
                    value:"ext1-attr2"
                },
                attr3 : {
                    value:"ext1-attr3",
                    setter: function(val) {
                        actualMethodCalls.push("ext1::attr3::setter");
                        return val;
                    }
                },
                attr4: {
                    value:"ext1-attr4"
                }
            };

            function Ext2() {
                actualMethodCalls.push("ext2::constructor");
            }

            Ext2.prototype.initializer = function() {
                actualMethodCalls.push("ext2::initializer");
            };

            Ext2.prototype.methodThree = function() {
                actualMethodCalls.push("ext2::methodThree");
            };

            Ext2.prototype.methodFour = function() {
                actualMethodCalls.push("ext2::methodFour");
            };

            Ext2.ATTRS = {
                attr3 : {
                    value:"ext2-attr3",
                    setter: function(val) {
                        actualMethodCalls.push("ext2::attr3::setter");
                        return val;
                    }
                },
                attr4 : {
                    value:"ext2-attr4"
                }
            };

            var MyClass = Y.Base.create("myClass", Y.Base, [Ext1, Ext2], {
                
                initializer: function() {
                    actualMethodCalls.push("myClass::initializer");
                },
                
                methodOne : function() {
                    actualMethodCalls.push("myClass::methodOne");
                },
                
                methodTwo : function() {
                    actualMethodCalls.push("myClass::methodTwo");
                },

                methodFive : function() {
                    actualMethodCalls.push("myClass::methodFive");
                }
            }, { 
                ATTRS : {
                    attr1 : {
                        value:"myClass-attr1"
                    },
                    attr5 : {
                        value:"myClass-attr5"
                    }
                }
            });
            
            var o1 = new MyClass();
            var o2 = new MyClass();
            
            Y.Assert.areEqual("myClass-attr1", o1.get("attr1"), "o1 attr1 incorrect");
            Y.Assert.areEqual("myClass-attr1", o2.get("attr1"), "o2 attr1 incorrect");

            Y.Assert.areEqual("ext1-attr2", o1.get("attr2"), "o1 attr2 incorrect");
            Y.Assert.areEqual("ext1-attr2", o2.get("attr2"), "o2 attr2 incorrect");

            Y.Assert.areEqual("ext2-attr3", o1.get("attr3"), "o1 attr3 incorrect");
            Y.Assert.areEqual("ext2-attr3", o2.get("attr3"), "o2 attr3 incorrect");

            Y.Assert.areEqual("ext2-attr4", o1.get("attr4"), "o1 attr4 incorrect");
            Y.Assert.areEqual("ext2-attr4", o2.get("attr4"), "o2 attr4 incorrect");

            Y.Assert.areEqual("myClass-attr5", o1.get("attr5"), "o1 attr5 incorrect");
            Y.Assert.areEqual("myClass-attr5", o2.get("attr5"), "o2 attr5 incorrect");

            o1.methodOne();
            o2.methodOne();
            o1.methodTwo();
            o2.methodTwo();
            o1.methodThree();
            o2.methodThree();
            o1.methodFour();
            o2.methodFour();
            o1.methodFive();
            o2.methodFive();
            
            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        },
        
        "test:classstructure" : function() {
            function Ext1() {}
            Ext1.prototype.extOne = function() {};

            function Ext2() {}
            Ext2.prototype.extTwo = function() {};

            var MyClassTwo = Y.Base.create("myClassTwo", Y.Base, [Ext1, Ext2], {
                initializer: function() {},
                methodOne: function() {}
            });

            var MyClassOne = Y.Base.create("myClassOne", Y.Base, [Ext1], {
                initializer: function() {},
                methodOne: function() {}
            });
            
            var o1 = new MyClassOne();
            var o2 = new MyClassTwo();

            Y.Assert.isTrue(o1.hasImpl(Ext1), "o1 should pass hasImpl(Ext1)");
            Y.Assert.isFalse(o1.hasImpl(Ext2),  "o1 should fail hasImpl(Ext2)");

            Y.Assert.isTrue(o2.hasImpl(Ext1),  "o2 should pass hasImpl(Ext1)");
            Y.Assert.isTrue(o2.hasImpl(Ext2), "o2 should pass hasImpl(Ext1)");
            
            Y.Assert.isTrue(o1 instanceof MyClassOne, "o1 should be an instanceof MyClassOne");
            Y.Assert.isTrue(o1 instanceof Y.Base, "o1 should be an instanceof Base");
            
            Y.Assert.isTrue(o2 instanceof MyClassTwo, "o2 should be an instanceof MyClassTwo");
            Y.Assert.isTrue(o2 instanceof Y.Base, "o2 should be an instanceof Base");

            Y.Assert.isFalse(o1 instanceof MyClassTwo, "o1 should NOT be an instanceof MyClassTwo");
            Y.Assert.isFalse(o2 instanceof MyClassOne, "o2 should NOT be an instanceof MyClassOne");
            
            Y.Assert.isFunction(o1.methodOne, "o1 should have a methodOne method");
            Y.Assert.isFunction(o1.extOne, "o1 should have an extOne method");
            Y.Assert.isUndefined(o1.extTwo, "o1 should not have an extTwo method");

            Y.Assert.isFunction(o2.methodOne, "o2 should have a methodOne method");
            Y.Assert.isFunction(o2.extOne, "o2 should have an extOne method");
            Y.Assert.isFunction(o2.extTwo, "o2 should have an extTwo method");

            Y.Assert.isTrue(MyClassOne.superclass.constructor === Y.Base, "MyClassOne should have superclass set to Base");
            Y.Assert.isTrue(MyClassTwo.superclass.constructor === Y.Base, "MyClassTwo should have superclass set to Base");

            // Make sure Y.Base was untouched.
            var b = new Y.Base();

            Y.Assert.isUndefined(b.methodOne, "Base should not have extension methods");
            Y.Assert.isUndefined(b.extOne, "Base should not have extension methods");
            Y.Assert.isUndefined(b.extTwo, "Base should not have extension methods");
            Y.Assert.isFalse(MyClassOne === Y.Base);
            Y.Assert.isFalse(MyClassTwo === Y.Base);
        },

        "test:extend" : function() {
            
            var actualMethodCalls = [],
                expectedMethodCalls = [
                    "ext1::constructor",
                    "myClassOne::initializer",
                    "ext1::initializer",
                    "ext2::constructor",
                    "myClassTwo::initializer",
                    "ext2::initializer",
                    "myClassOne::methodOne",
                    "myClassTwo::methodTwo",
                    "ext1::extOne",
                    "ext2::extTwo"
                ];

            function Ext1() {
                actualMethodCalls.push("ext1::constructor");                
            }
            Ext1.prototype.extOne = function() {
                actualMethodCalls.push("ext1::extOne");
            };
            Ext1.prototype.initializer = function() {
                actualMethodCalls.push("ext1::initializer");
            };

            function Ext2() {
                actualMethodCalls.push("ext2::constructor");
            }
            Ext2.prototype.extTwo = function() {
                actualMethodCalls.push("ext2::extTwo");
            };
            Ext2.prototype.initializer = function() {
                actualMethodCalls.push("ext2::initializer");
            };

            var MyClassOne = Y.Base.create("myClassOne", Y.Base, [Ext1], {
                initializer: function() {
                    actualMethodCalls.push("myClassOne::initializer");    
                },
                methodOne: function() {
                    actualMethodCalls.push("myClassOne::methodOne");
                }
            });

            var MyClassTwo = Y.Base.create("myClassTwo", MyClassOne, [Ext2], {
                initializer: function() {
                    actualMethodCalls.push("myClassTwo::initializer");
                },
                methodTwo: function() {
                    actualMethodCalls.push("myClassTwo::methodTwo");
                }
            });

            var o = new MyClassTwo();
            o.methodOne();
            o.methodTwo();
            o.extOne();
            o.extTwo();

            Y.ArrayAssert.itemsAreEqual(expectedMethodCalls, actualMethodCalls, "Unexpected method calls");
        }

    }));

    Y.Test.Runner.setName("Base Tests");
    Y.Test.Runner.add(suite);
    Y.Test.Runner.disableLogging();
    Y.Test.Runner.run();

    var console;

    Y.one("#btnRun").set("disabled", false).on("click", function() {
        if (!console) {
            console = new Y.Console({
                id:"console",
                width:"100%",
                height:"90%",
                verbose : false,
                printTimeout: 0,
                newestOnTop : false,
                entryTemplate: '<pre class="{entry_class} {cat_class} {src_class}">'+
                        '<span class="{entry_cat_class}">{label}</span>'+
                        '<span class="{entry_content_class}">{message}</span>'+
                '</pre>'
            }).render();
        }

        Y.Test.Runner.enableLogging();
        Y.Test.Runner.run();
    });
});
</script>
<p><input type="button" value="Run Tests" id="btnRun" disabled=true></p>
</body>
</html>
